﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;

using HadronData;

using Hadron.SpecialEffects;

namespace Hadron.Entities
{
    class Reactor
        : LandEntity
    {
        private static Polygon s_polygonContact, s_polygonVisible;

        private double m_dTime;
        private Polygon m_polygonContact, m_polygonVisible;
        private ParticleSystem m_particleSystem1, m_particleSystem2;
        private SoundEffectInstance m_soundEffectInstanceReactor;

        public Reactor(EntityMarker p_entityMarker, Environment p_environment)
            : base(p_entityMarker, p_environment)
        {
            if (s_polygonContact == null)
            {
                s_polygonVisible = new Polygon();

                s_polygonVisible.Edges.Add(new Edge(-24.0f,   0.0f, -22.0f,  -8.0f, Color.Gray));
                s_polygonVisible.Edges.Add(new Edge(-22.0f,  -8.0f,  22.0f,  -8.0f, Color.Gray));
                s_polygonVisible.Edges.Add(new Edge( 22.0f,  -8.0f,  24.0f,   0.0f, Color.Gray));

                s_polygonVisible.Edges.Add(new Edge(-24.0f, -52.0f, -22.0f, -48.0f, Color.Gray));
                s_polygonVisible.Edges.Add(new Edge(-22.0f, -48.0f,  22.0f, -48.0f, Color.Gray));
                s_polygonVisible.Edges.Add(new Edge( 22.0f, -48.0f,  24.0f, -52.0f, Color.Gray));

                s_polygonVisible.Edges.Add(new Edge(-24.0f, -52.0f, -17.0f, -60.0f, Color.Gray));
                s_polygonVisible.Edges.Add(new Edge(-17.0f, -60.0f,  -6.0f, -64.0f, Color.Gray));
                s_polygonVisible.Edges.Add(new Edge( -6.0f, -64.0f,   6.0f, -64.0f, Color.Gray));
                s_polygonVisible.Edges.Add(new Edge( 24.0f, -52.0f,  17.0f, -60.0f, Color.Gray));
                s_polygonVisible.Edges.Add(new Edge( 17.0f, -60.0f,   6.0f, -64.0f, Color.Gray));

                s_polygonVisible.Edges.Add(new Edge(-18.0f,  -8.0f, -18.0f, -48.0f, Color.YellowGreen));
                s_polygonVisible.Edges.Add(new Edge( 18.0f,  -8.0f,  18.0f, -48.0f, Color.YellowGreen));
                s_polygonVisible.Edges.Add(new Edge(-16.0f,  -8.0f, -16.0f, -48.0f, Color.Green));
                s_polygonVisible.Edges.Add(new Edge( 16.0f,  -8.0f,  16.0f, -48.0f, Color.Green));
                s_polygonVisible.UpdateBounds();

                s_polygonContact = new Polygon(s_polygonVisible);
            }

            m_nHealth = 20;
            m_nPoints = 2500;

            m_polygonContact = new Polygon(s_polygonContact);
            m_polygonVisible = new Polygon(s_polygonVisible);

            m_particleSystem1 = new ParticleSystem(32, 32.0f, 1.0f);
            m_particleSystem1.ParticleColours = new Color[] { Color.Green, Color.OrangeRed };
            m_particleSystem1.Active = true;
            m_particleSystem2 = new ParticleSystem(32, 32.0f, 1.0f);
            m_particleSystem2.ParticleColours = new Color[] { Color.OrangeRed, Color.Green };
            m_particleSystem2.Active = true;

            m_circleBounds = s_polygonContact.GetBoundingCircle(Vector2.Zero);

            m_soundEffectInstanceReactor
                = AssetManager.Sounds.Reactor.Play(0.0f, 0.0f, 0.0f, true);
        }

        public override void OnDestroy()
        {
            m_soundEffectInstanceReactor.Stop();
            m_environment.SpecialEffects.Add(
                new Explosion(m_environment, m_trnPlacement.Apply(Vector2.UnitY * -24.0f), 1.5f, 2.0f));
            ++m_environment.PlayerShip.ReactorsDestroyed;
        }

        public override void OnDeactivate()
        {
            m_soundEffectInstanceReactor.Stop();
        }

        public override void Update(GameTime p_gameTime)
        {
            base.Update(p_gameTime);

            m_circleBounds.Centre = m_trnPlacement.Translation;

            m_dTime = p_gameTime.TotalGameTime.TotalSeconds;

            m_polygonContact.Transform(m_trnPlacement, s_polygonContact);
            m_polygonVisible.Transform(m_trnPlacement, s_polygonVisible);

            float fParticleOffset = ((float)s_random.NextDouble() - 0.5f) * 16.0f;
            m_particleSystem1.Position = m_trnPlacement.Apply(new Vector2(fParticleOffset, -10.0f));
            m_particleSystem1.EmissionVelocity = m_trnPlacement.RotationComponent.Apply(Vector2.UnitY * -32.0f);
            m_particleSystem1.Update(p_gameTime);

            fParticleOffset = ((float)s_random.NextDouble() - 0.5f) * 16.0f;
            m_particleSystem2.Position = m_trnPlacement.Apply(new Vector2(fParticleOffset, -46.0f));
            m_particleSystem2.EmissionVelocity = m_trnPlacement.RotationComponent.Apply(Vector2.UnitY * 32.0f);
            m_particleSystem2.Update(p_gameTime);

            m_soundEffectInstanceReactor.Volume = m_environment.ComputeSoundVolume(Position);
        }

        public override void Draw(SpriteBatch p_spriteBatch)
        {
            m_polygonVisible.Draw(p_spriteBatch);
            m_particleSystem1.Draw(p_spriteBatch);
            m_particleSystem2.Draw(p_spriteBatch);

            Vector2 vecPositionLight1 = m_trnPlacement.Apply(new Vector2(-16, -52.0f));
            Vector2 vecPositionLight2 = m_trnPlacement.Apply(new Vector2(-16, -4.0f));
            Vector2 vecLightOffset = m_trnPlacement.RotationComponent.Apply(new Vector2(5.0f, 0.0f));
            Vector2 vecOrigin = new Vector2(8.0f, 8.0f);
            for (int nIndex = 0; nIndex < 8; nIndex++)
            {
                float fOpacity = (float) Math.Abs(Math.Cos((nIndex + m_dTime * 4.0) * MathHelper.Pi * 0.125));
                p_spriteBatch.Draw(AssetManager.Textures.GlowLine,
                    vecPositionLight1 + vecLightOffset * nIndex, null,
                    new Color(Color.Red, fOpacity), 0.0f, vecOrigin, 1.0f,
                    SpriteEffects.None, 0.0f);
                p_spriteBatch.Draw(AssetManager.Textures.GlowLine,
                    vecPositionLight2 + vecLightOffset * nIndex, null,
                    new Color(Color.SkyBlue, 1.0f - fOpacity), 0.0f, vecOrigin, 1.0f,
                    SpriteEffects.None, 0.0f);
            }
        }

        public override HadronData.EntityType Type
        {
            get { return EntityType.Reactor; }
        }

        public override bool Hostile
        {
            get { return true; }
        }

        public override bool Destructuble
        {
            get { return true; }
        }

        public override Geometry Geometry
        {
            get { return m_polygonVisible; }
        }
    }
}
